package com.fujimana.rockincat.restree.web.map;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;

public class ServletContextMap implements java.util.Map<String, Object> {

	private ServletContext servletContext;

	public ServletContextMap(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void clear() {
		Enumeration enumeration = servletContext.getAttributeNames();
		List<String> keys = new ArrayList<String>();

		while (enumeration.hasMoreElements()) {
			keys.add((String) enumeration.nextElement());
		}

		for (String key : keys) {
			this.servletContext.removeAttribute(key);
		}
	}

	@Override
	public boolean containsKey(Object key) {
		return servletContext.getAttribute((String) key) != null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean containsValue(Object value) {
		Enumeration enumeration = servletContext.getAttributeNames();

		while (enumeration.hasMoreElements()) {
			String key = (String) enumeration.nextElement();

			if (value.equals(this.servletContext.getAttribute(key))) {
				return true;
			}
		}

		return false;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<java.util.Map.Entry<String, Object>> entrySet() {
		Set<java.util.Map.Entry<String, Object>> ret = new HashSet<Entry<String, Object>>();

		Enumeration enumeration = servletContext.getAttributeNames();
		while (enumeration.hasMoreElements()) {
			String key = (String) enumeration.nextElement();

			ret.add(new ServletContextMapEntry(key, this.servletContext));
		}

		return ret;
	}

	@Override
	public Object get(Object key) {
		return this.servletContext.getAttribute((String) key);
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean isEmpty() {
		Enumeration enumeration = servletContext.getAttributeNames();
		return enumeration.hasMoreElements();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<String> keySet() {
		Enumeration enumeration = servletContext.getAttributeNames();
		Set<String> keys = new HashSet<String>();

		while (enumeration.hasMoreElements()) {
			keys.add((String) enumeration.nextElement());
		}
		return keys;
	}

	@Override
	public Object put(String key, Object value) {
		Object old = this.servletContext.getAttribute(key);
		this.servletContext.setAttribute(key, value);
		return old;
	}

	@Override
	public void putAll(Map<? extends String, ? extends Object> m) {
		for (Map.Entry<? extends String, ? extends Object> entry : m.entrySet()) {
			this.servletContext.setAttribute(entry.getKey(), entry.getValue());
		}

	}

	@Override
	public Object remove(Object key) {
		Object value = this.servletContext.getAttribute((String) key);

		if (value != null) {
			this.servletContext.removeAttribute((String) key);
		}

		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public int size() {
		Enumeration enumeration = servletContext.getAttributeNames();

		int size = 0;
		while (enumeration.hasMoreElements()) {
			size++;
		}

		return size;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Collection<Object> values() {
		Enumeration enumeration = servletContext.getAttributeNames();
		List<Object> keys = new ArrayList<Object>();

		while (enumeration.hasMoreElements()) {
			keys.add(this.servletContext.getAttribute((String) enumeration
					.nextElement()));
		}
		return keys;
	}

	class ServletContextMapEntry implements Entry<String, Object> {
		private ServletContext servletContext;
		
		private String key;

		ServletContextMapEntry(String key, ServletContext servletContext) {
			this.key = key;
			this.servletContext = servletContext;
		}

		@Override
		public String getKey() {
			return key;
		}

		@Override
		public Object getValue() {
			return servletContext.getAttribute(key);
		}

		@Override
		public Object setValue(Object value) {
			Object old = getValue();
			servletContext.setAttribute(key, value);
			
			return old;
		}

	}
}
